package com.clei.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.clei.entity.Person;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 代码处理工具
 *
 * @author Y
 * @date 2023-10-09
 **/
public class CodeUtil {

    /**
     * 简单类型集
     */
    private final static Set<String> BASE_CLASS_SET =
            new HashSet<>(Arrays.asList("Byte", "Short", "Integer", "Long", "Double", "Float", "Boolean", "Character", "String"));

    public static void main(String[] args) {
        String str = convertMethod(Person.class, Person.class);
        PrintUtil.println(str);
    }

    /**
     * jsonStringToClassCode
     *
     * @param str jsonString
     */
    public static void jsonToClass(String str) {
        if (StringUtil.isBlank(str)) {
            return;
        }
        JSONObject jsonObject = JSONObject.parseObject(str);
        jsonToClass(null, jsonObject);
    }

    /**
     * jsonStringToClassCode
     *
     * @param curClassName 当前类名
     * @param jsonObject   JSONObject
     */
    public static void jsonToClass(String curClassName, JSONObject jsonObject) {
        if (CollectionUtil.isEmpty(jsonObject)) {
            return;
        }
        Map<String, String> map = new HashMap<>(jsonObject.size());
        jsonObject.forEach((k, v) -> {
            String className = getClassName(k, v);
            String key = StringUtil.snake2Camel(k);
            String value = String.format("\n/**\n" +
                    "     * %s\n" +
                    "     */\n@JsonProperty(\"%s\")\nprivate %s %s;", key, k, className, key);
            map.put(key, value);
        });

        curClassName = null == curClassName ? "BaseClass" : curClassName;
        PrintUtil.log("--------{}--------", curClassName);
        List<String> propertyList = map.keySet().stream().sorted().map(map::get).collect(Collectors.toList());
        for (String s : propertyList) {
            PrintUtil.println(s);
        }
        PrintUtil.log("--------{}--------", curClassName);
    }

    /**
     * 常用的convert 方法生成
     *
     * @param reqClass 入参class
     * @param resClass 出参class
     * @return String
     */
    public static String convertMethod(Class<?> reqClass, Class<?> resClass) {
        String reqClassName = reqClass.getSimpleName(), resClassName = resClass.getSimpleName(), req = "req", res = "res";
        StringBuilder sb = new StringBuilder();
        // 方法注释
        String commentTemp = "/**\n" +
                "     * convert\n" +
                "     *\n" +
                "     * @param req %s\n" +
                "     * @return %s\n" +
                "     */\n";
        String comment = String.format(commentTemp, reqClassName, resClassName);
        sb.append(comment);
        // 方法头
        sb.append("public ")
                .append(resClassName)
                .append(" convert(")
                .append(reqClassName)
                .append(" req) {\n")
                .append(resClassName)
                .append(' ')
                .append(res)
                .append(" = new ")
                .append(resClassName)
                .append("();\n");
        // set
        Field[] resFieldArr = resClass.getDeclaredFields();
        Set<String> reqFieldSet = Arrays.stream(reqClass.getDeclaredFields())
                .map(Field::getName).collect(Collectors.toSet());
        for (Field f : resFieldArr) {
            String property = f.getName();

            String prefix = reqFieldSet.contains(property) ? "" : "// ";
            sb.append(prefix);
            property = Character.toUpperCase(property.charAt(0)) + property.substring(1);
            sb.append(res)
                    .append(".set")
                    .append(property)
                    .append('(')
                    .append(req)
                    .append(".get")
                    .append(property)
                    .append("());\n");
        }
        // end
        sb.append("return res;\n");
        sb.append("}");
        return sb.toString();
    }

    /**
     * getClassName
     *
     * @param key key
     * @param v   v
     * @return className
     */
    private static String getClassName(String key, Object v) {
        if (null == v) {
            return "Object";
        }
        String className = v.getClass().getSimpleName();
        if (BASE_CLASS_SET.contains(className)) {
            return className;
        }
        boolean isList = false;
        // list
        if (v instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) v;
            if (CollectionUtil.isEmpty(jsonArray)) {
                return "List<Object>";
            }
            // 数组里是否是简单类
            v = jsonArray.get(0);
            className = v.getClass().getSimpleName();
            if (BASE_CLASS_SET.contains(className)) {
                return String.format("List<%s>", className);
            }
            isList = true;
        }
        // obj
        className = StringUtil.snake2Camel(key, true);
        if (v instanceof JSONObject) {
            JSONObject jsonObject = (JSONObject) v;
            jsonToClass(className, jsonObject);
        }
        return isList ? String.format("List<%s>", className) : className;
    }
}